

/**
 * 我希望这个checkFunc能达到的要求是，能访问当前节点和前置条件节点的数据
 */



/* check functions */
const checkDoubleQuote = function(str, index, node) { // 还需要检查前面是不是有‘\’
  return str === '"';
};

const checkLengthNotZero = function(char, index, node) {
  const start = node.pre.index;
  let p = node.pre;
  while (p.next && p.next !== node) {
    p = p.next;
  }
  const end = p.index;
  return end - start > 1;
};
function checkColon(char: string) {
  return char === ':';
}
/* =========== */

function genconNodes(cons, createNode) {
  let root;
  let p;
  cons.forEach(item => {
    const main = createNode(item.con, item.effect);
    if (!root) root = main;
    if (p) p.next = main;
    p = main;
    if (Array.isArray(item.pre)) {
      p.pre = createNode(item.pre[0]);
      p = p.pre;
      item.pre.slice(1).forEach(con => {
        p.next = createNode(con);
        p = p.next;
      });
      p.next = main;
    }
  });
  return root;
}
// 感觉还需要一个树装数据结构来描述这个条件，那么得先生成这个树状结构
// 树状结构的节点 需要存贮一些其他数据，比如目前字符串的位置。
const conditions = [
  {
    con: checkLengthNotZero,
    pre: [checkDoubleQuote, checkDoubleQuote],
    effect: (node) => {
      const start = node.pre.index;
      let p = node.pre;
      while (p.next && p.next !== node) {
        p = p.next;
      }
      const end = p.index;
      return end - start > 1;
    }
  }, 
  {
    con: checkColon,
  },
  {
    con: checkDoubleQuote,
  }
];

class MatchKeyValue {
  constructor(conditions) {
    this.input = '';
    this.index = 0;
    this.rootNode = genconNodes(conditions, (checkFunc, effect) => {
      return {
        check: this.connect(checkFunc),
        effect,
        index: null,
        next: null,
        pre: null,
      };
    });
    this.pointer = this.rootNode;
  }
  iterator = () => {
    const len = this.input.length;
    for (let i = 0; i < len; i++, this.index += 1) {
      const result = this.pointer.check();
      if (result) this.move(this.pointer);
    }
  }
  connect = (func) => {
    return () => {
      const start = node.pre;
      let p = node.pre;
      while (p.next && p.next !== node) {
        p = p.next;
      }
      const end = p;
      const res = func(this.input, this.index, this.pointer);
      if (res) {
        this.pointer.index = this.index;
        if (typeof this.pointer.effect === 'function') {
          this.pointer.effect()
        } 
      }
      return res;
    };
  }
  coonectEffect = (func) => {
    return () => {
      func(this.input, )
    };
  }
  move = (node) => {
    if (node.pre) {
      this.pointer = node.pre;
    } else {
      this.pointer = node.next;
    }
  }
  setInput = (val) => {
    this.input = val;
    this.index = 0;
    this.pointer = this.rootNode;
  }
}